package com.molichuxing.services.business.service.impl;

import com.molichuxing.framework.dto.Paged;
import com.molichuxing.framework.dto.TabDto;
import com.molichuxing.framework.exception.BizException;
import com.molichuxing.framework.utils.DateUtil;
import com.molichuxing.framework.utils.ObjectCastUtil;
import com.molichuxing.services.business.convertor.Convert;
import com.molichuxing.services.business.dto.request.modify.CarCommercialInsuranceModifyDto;
import com.molichuxing.services.business.dto.request.modify.CarCompulsoryInsuranceModifyDto;
import com.molichuxing.services.business.dto.request.modify.MaintenanceModifyDto;
import com.molichuxing.services.business.dto.response.*;
import com.molichuxing.services.business.service.CarInsuranceBizService;
import com.molichuxing.services.business.service.MaintenanceBizService;
import com.molichuxing.services.infrastructure.dto.request.create.MaintenanceLogCreateDto;
import com.molichuxing.services.infrastructure.dto.response.*;
import com.molichuxing.services.infrastructure.dto.response.CarDto;
import com.molichuxing.services.infrastructure.service.*;
import com.molichuxing.services.property.CarInsuranceTypeEnum;
import com.molichuxing.services.property.MaintenanceStatusEnum;
import com.molichuxing.services.property.MaintenanceTabEnum;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 保养 服务实现类
 * </p>
 *
 * @author
 * @since 2019-08-15
 */
@Service("maintenanceBizService")
public class MaintenanceBizServiceImpl implements MaintenanceBizService {

  private static final Logger log = Logger.getLogger(MaintenanceBizServiceImpl.class);

  @Resource
  private CarService carService;

  @Resource
  private MaintenanceService maintenanceService;

  @Resource
  private MaintenanceLogService maintenanceLogService;

    @Resource
    private MaintenanceConfigService maintenanceConfigService;

  @Override
  public Paged<MaintenanceBizDto> getMaintenancePage(Map<String, Object> mapParam, Integer pageNum, Integer pageSize) {
    Paged<MaintenanceBizDto> pageResult = new Paged<>();
    pageResult.setTab(getTabList());
      String vin = ObjectCastUtil.castString(mapParam.get("vin"));
      String licencePlate = ObjectCastUtil.castString(mapParam.get("licencePlate"));
      if(StringUtils.isNoneBlank(vin) || StringUtils.isNoneBlank(licencePlate)) {
      CarDto carDto = carService.getByVinLicencePlate(vin,licencePlate);
      if(null == carDto) {
        return pageResult;
      }
      mapParam.put("vehicleId", carDto.getId());
    }
    if(Integer.parseInt(mapParam.get("type").toString())== MaintenanceTabEnum.AUDIT_RECORD.getValue()) {
        Paged<MaintenanceLogDto> pageMaintenanceLogResult = maintenanceLogService.getMaintenanceLogPage(mapParam, pageNum, pageSize);
        Convert.toMaintenanceLogBizDto(pageResult, pageMaintenanceLogResult);
    }else {
        if(Integer.parseInt(mapParam.get("type").toString())== MaintenanceTabEnum.MAINTENANCE.getValue()){
            List<Integer> statusList=new ArrayList<>();
            statusList.add(MaintenanceStatusEnum.WAITING_MAINTENANCE.getValue());
            statusList.add(MaintenanceStatusEnum.AUDIT_REJECTED.getValue());
            mapParam.put("statusList",statusList);
            mapParam.put("type",null);
        }
        Map<Integer, MaintenanceLogDto> submitUserMap = new HashMap<>();
        Paged<MaintenanceDto> pageMaintenanceResult = maintenanceService.getMaintenancePage(mapParam, pageNum, pageSize);
        if(null != pageMaintenanceResult && null != pageMaintenanceResult.getList()) {
            for(MaintenanceDto maintenanceDto : pageMaintenanceResult.getList()) {
                MaintenanceLogDto maintenanceLogDto = maintenanceLogService.getMaintenanceLogByPId(maintenanceDto.getId());
                if(null != maintenanceLogDto) {
                    submitUserMap.put(maintenanceDto.getId(), maintenanceLogDto);
                }
            }
        }
        Convert.toMaintenanceBizDto(pageResult, pageMaintenanceResult, submitUserMap);

    }
      Map<Integer, CarDto> carMap = new HashMap<>();
      if((null != pageResult)&&(null != pageResult.getList())) {
          carMap = carService.getCarByIds(pageResult.getList().stream().map(e -> e.getCarId()).collect(Collectors.toList()));
      }
      maintenanceCar(pageResult.getList(), carMap);
    return pageResult;
  }

    @Override
    public MaintenanceDetailBizDto getMaintenance(Integer id) throws Exception {
        MaintenanceDto maintenanceDto = maintenanceService.getMaintenance(id);
        if(null == maintenanceDto) {
            return null;
        }
        CarDto carDto = carService.getCarById(maintenanceDto.getCarId());
        MaintenanceDetailBizDto maintenanceDetail = new MaintenanceDetailBizDto();
        maintenanceDetail.setBasic(Convert.toMaintenanceBasicBizDto(maintenanceDto, carDto));

        List<MaintenanceLogDto> maintenanceLogList = maintenanceLogService.getMaintenanceLogList(maintenanceDto.getCarId(), Arrays.asList(MaintenanceStatusEnum.AUDIT_PASS.getValue(), MaintenanceStatusEnum.AUDIT_REJECTED.getValue()));
        maintenanceDetail.setRecordList(Convert.toMaintenanceRecordBizDto(maintenanceLogList));

        List<MaintenanceLogDto> auditMaintenanceLogList = maintenanceLogService.getMaintenanceLogList(maintenanceDto.getCarId(), Arrays.asList(MaintenanceStatusEnum.AUDITED.getValue(), MaintenanceStatusEnum.AUDIT_PASS.getValue()));
        if(null != auditMaintenanceLogList && auditMaintenanceLogList.size() > 0) {
            MaintenanceLogDto maintenanceLogDto = auditMaintenanceLogList.stream().sorted(Comparator.comparing(MaintenanceLogDto::getGmtModified).reversed()).collect(Collectors.toList()).get(0);
            if(maintenanceLogDto.getStatus() != MaintenanceStatusEnum.AUDIT_PASS.getValue()) {
                maintenanceDetail.setInfo(Convert.toMaintenanceInfoBizDto(maintenanceLogDto));
            }
        }
        return maintenanceDetail;
    }

    @Override
    public List<MaintenanceRecordBizDto> getMaintenanceByCarId(Integer carId) throws Exception {
        List<MaintenanceLogDto> maintenanceLogList = maintenanceLogService.getMaintenanceLogList(carId, Arrays.asList(MaintenanceStatusEnum.AUDIT_PASS.getValue(), MaintenanceStatusEnum.AUDIT_REJECTED.getValue()));
        return Convert.toMaintenanceRecordBizDto(maintenanceLogList);
    }

    @Override
    public int modifyMaintenanceCheck(MaintenanceModifyDto modifyDto)throws Exception {
        MaintenanceLogDto maintenanceLogDto = maintenanceLogService.getMaintenanceLogByPId(modifyDto.getMaintenanceLogId());
        if(null == maintenanceLogDto) {
            throw new BizException("保养信息不存在");
        }
        MaintenanceDto maintenance = maintenanceService.getMaintenance(maintenanceLogDto.getMaintenanceId());
        if(null == maintenance) {
            throw new BizException("保养信息不存在");
        }
        CarDto carDto = carService.getCarById(maintenanceLogDto.getCarId());
        if(null == carDto) {
            throw new BizException("车辆数据不存在");
        }
        MaintenanceDto maintenanceDto = new MaintenanceDto();
        maintenanceDto.setId(maintenanceLogDto.getMaintenanceId());
        maintenanceDto.setStatus(MaintenanceStatusEnum.getEnum(modifyDto.getStatus()).getValue());
        if(modifyDto.getStatus() == MaintenanceStatusEnum.AUDIT_PASS.getValue()) {
            maintenanceDto.setCount(maintenance.getCount()+1);
            MaintenanceConfigDto maintenanceConfigDto = maintenanceConfigService.getMaintenanceConfigByVehicleId(carDto.getVehicleId());
            if(null == maintenanceConfigDto) {
                throw new BizException("保养信息不存在");
            }
            maintenanceDto.setMaintainableDate(DateUtil.plus(maintenanceLogDto.getActualMaintainDate().atStartOfDay(),maintenanceConfigDto.getMaintenanceTime(), ChronoUnit.DAYS));
            maintenanceDto.setMaintainableMileage(maintenanceLogDto.getActualMaintainMileage().add(maintenanceConfigDto.getMileage()));
        }
        maintenanceService.updateMaintenanceById(maintenanceDto);
        modifyDto.setMaintenanceLogId(maintenanceLogDto.getId());
        MaintenanceLogCreateDto maintenanceLogCreateDto = new MaintenanceLogCreateDto();
        BeanUtils.copyProperties(maintenanceLogDto, maintenanceLogCreateDto);
        maintenanceLogCreateDto.setStatus(modifyDto.getStatus());
        maintenanceLogCreateDto.setOperationType(1);
        maintenanceLogCreateDto.setOperationId(modifyDto.getOperateId());
        maintenanceLogCreateDto.setId(null);
        maintenanceLogCreateDto.setRejectReason(modifyDto.getRejectReason());
        maintenanceLogCreateDto.setCheckDate(LocalDateTime.now());
        return maintenanceLogService.createMaintenanceLog(maintenanceLogCreateDto);
    }

    private static void maintenanceCar(List<MaintenanceBizDto> maintenanceList, Map<Integer, CarDto> carMap){
        if((null != maintenanceList)&&(maintenanceList.size() > 0)) {
            for(MaintenanceBizDto bean : maintenanceList) {
                if((null != carMap)&&(null !=carMap.get(bean.getCarId()))) {
                    bean.setVin(carMap.get(bean.getCarId()).getVin());
                    bean.setLicencePlate(carMap.get(bean.getCarId()).getLicencePlate());
                    bean.setVehicleId(carMap.get(bean.getCarId()).getVehicleId());
                    bean.setVehicleType(carMap.get(bean.getCarId()).getVehicleType());
                    bean.setStockId(carMap.get(bean.getCarId()).getStockId());
                }
            }
        }
  }

  private List<TabDto> getTabList() {
    List<TabDto> tabList = new ArrayList<>();
    for(MaintenanceTabEnum statusEnum : MaintenanceTabEnum.values()) {

      int count = 0;
      if(statusEnum == MaintenanceTabEnum.AUDIT_RECORD) {
          Map<String, Object> map = new HashMap<>();
          map.put("type", MaintenanceTabEnum.AUDIT_RECORD.getValue());
          count = maintenanceLogService.getCount(map);
      }else if(statusEnum == MaintenanceTabEnum.AUDITED)  {
          count = maintenanceService.getCount(statusEnum);
      }else {
          count = maintenanceService.getCount(statusEnum);
      }
      TabDto tabDto = new TabDto();
      tabDto.setCount(count);
      tabDto.setName(statusEnum.getName());
      tabDto.setType(statusEnum.getValue());
      tabList.add(tabDto);
    }
    return tabList;
  }

}
